#include <unistd.h>
#include "game-printer.h"
#include "MyMap.h"
#include "SnakePlayer.h"
#include "ServerSideSynchronizer.h"
#include "ClientSideSynchronizer.h"

void gp_print_current_state(AppData *data)
{

	MyMap * map = MyMap::instanceOf();

	for (int i=0; i < MAP_X; ++i)
	{
		for (int j=0; j < MAP_Y; ++j)
		{
			if (map->mine == map->getMapCharIfChanged(i, j) )
			{
				/* print 1*/
				mvwaddch(data->main_win, j, i, 'X');
			}
			if (map->empty_field == map->getMapCharIfChanged(i, j) )
			{
				/* print 1*/
				mvwaddch(data->main_win, j, i, ' ');
			}
			else if ( '1' == map->getMapCharIfChanged(i, j) )
			{
				/* print 1*/
				wattron(data->main_win, COLOR_PAIR(3));
				mvwaddch(data->main_win, j, i, SNAKE_SEGMENT_CHAR);
				wattroff(data->main_win, COLOR_PAIR(3));
			}
			else if ( '0' == map->getMapCharIfChanged(i, j) )
			{
							/* print 1*/
							wattron(data->main_win, COLOR_PAIR(2));
							mvwaddch(data->main_win, j, i, SNAKE_SEGMENT_CHAR);
							wattroff(data->main_win, COLOR_PAIR(2));
			}
			else
			{

				/*	mvwaddch(data->main_win, j, i, map->getMapCharAt(i, j) );*/

			}
		}
	}

	wrefresh(data->main_win);

	return;
}
void gp_inform_on_middle(AppData* data, char * message)
{
	mvwprintw(data->main_win, CONSOLE_Y_RES /2, 
	CONSOLE_X_RES /2 - strlen(message) / 2, message);
	wrefresh(data->main_win);

}

void gp_inform_lose_win(AppData * data, bool winner, int server_wins, int players_win,
                       		  char * player_name)
{

	char * win_lose = NULL;
	
	if ( true == winner)
	{
		win_lose = STRING_YOU_WIN;
	}
	else
	{
		win_lose = STRING_YOU_LOST;
	}
	
	mvwprintw(data->main_win, CONSOLE_Y_RES /2, 
		CONSOLE_X_RES /2 - strlen(win_lose) / 2, 
		win_lose);
	
	mvwprintw(data->main_win, CONSOLE_Y_RES /2 + 2, 
			CONSOLE_X_RES /2 - strlen(win_lose) / 2, 
			"Server %d",server_wins);
	
	mvwprintw(data->main_win, CONSOLE_Y_RES /2 + 3, 
				CONSOLE_X_RES /2 - strlen(win_lose) / 2, 
				"%s %d", player_name, players_win);
	wrefresh(data->main_win);
}

void gp_inform_game_over(AppData * data)
{
	mvwprintw(data->main_win, CONSOLE_Y_RES /2, 
	CONSOLE_X_RES /2 - strlen(STRING_GAME_OVER) / 2, 
	STRING_GAME_OVER);

	mvwprintw(data->main_win, CONSOLE_Y_RES /2 + 10, 
	CONSOLE_X_RES /2 - strlen(STRING_PRESS_KEY) / 2, 
	STRING_PRESS_KEY);
	wrefresh(data->main_win);
}



void gp_cleanup_map_and_wait_for_key(AppData * data)
{
	wclear(data->main_win);
	MyMap::instanceOf()->resetMapAndSnakes();
	MyMap::instanceOf()->markAllChanged();
	nodelay(data->main_win, FALSE);
	wgetch(data->main_win);
	nodelay(data->main_win, TRUE);
}

void gp_print_win_lost_message(int player_number, AppData * data, PlayerSynchronizer * synchronizer)
{
	int status = synchronizer->getPlayerWinLostStatus(player_number);
	
	switch(status)
	{
	case PLAYER_STATE_GAME_LOST:
		gp_inform_on_middle(data,STRING_YOU_LOST);
		MyMap::instanceOf()->resetMapAndSnakes();
			MyMap::instanceOf()->markAllChanged();
		sleep(1);
		break;
	case PLAYER_STATE_GAME_WIN:
		gp_inform_on_middle(data,STRING_YOU_WIN);
		MyMap::instanceOf()->resetMapAndSnakes();
			MyMap::instanceOf()->markAllChanged();
		sleep(1);
		break;
	default:
		break;
	}
}

void gp_client_gaming(AppData *data)
{
	int ch;
	int move_result = 0;/* result of move - test game over*/
	
	
	ClientSideSynchronizer * synchronizer =
			ClientSideSynchronizer::getInstance();
	synchronizer->setPlayerNumber(1);
	gp_inform_on_middle(data, STRING_WAITING_FOR_PLAYERS);
	
		
	//SnakePlayer * sp =new SnakePlayer(synchronizer->getPlayerNumber());
	SnakePlayer * sp = MyMap::getInstance()->getSnakePlayerByNumber( synchronizer->getPlayerNumber());
	//MyMap::getInstance()->resetMapAndSnakes();

	
	nodelay(data->main_win, TRUE);
	clearok(data->main_win, FALSE); /* not completely redraw window*/
	curs_set(0);

	wclear(data->main_win);
	while (1)
	{
		ch = wgetch(data->main_win);
		/*odpal wyswietlanie na ekranie */
		switch (ch)
		{
		case KEY_DOWN:
			/* Go to next field */
			data->last_move = SNAKE_DOWN;
			break;
		case KEY_UP:
			/* Go to previous field */
			data->last_move = SNAKE_UP;
			break;
		case KEY_LEFT:
			/* Go to previous field */
			data->last_move = SNAKE_LEFT;
			break;
		case KEY_RIGHT:
			/* Go to previous field */
			data->last_move = SNAKE_RIGHT;
			break;
		case KEY_BACKSPACE:
			//data->last_move = KEY_BACKSPACE;
			sp->backRevisionNum(10);
			break;
		default:
			/* If this is a normal character, it gets */
			/* Printed                                */
			//data->last_move = SNAKE;
			break;
		}

		/*
		 synchronizer->setClientLastDirection(0,data->last_move);
		 */
		
		//move_result = sp->moveTo(data->last_move);
		synchronizer->setLastDirection(data->last_move);
		//synchronizer->synchronize();
		//sp->moveTo(data->last_move);
		
		gp_print_current_state( data );
		synchronizer->incLocalRound();
		//usleep(TIME_DELAY * 5);

	}
}



void gp_do_test_gaming(AppData *data)
{

	data->last_move = SNAKE_UP;
	int ch;
	int move_result = 0;/* result of move - test game over*/
	if (1 == data->client_mode)
	{
		gp_client_gaming(data);
		return;
	}

	ServerSideSynchronizer * synchronizer =
			ServerSideSynchronizer::getInstance();


	wclear(data->main_win);

	gp_inform_on_middle(data, STRING_WAITING_FOR_PLAYERS);
#ifdef FAKE_REGISTER
	if ( 0 == ServerSideSynchronizer::getInstance()->processPlayersRegistration() )
	{
		gp_inform_on_middle(data, STRING_NOBODY_CONNECTED);
		sleep(NONE_PLAYERS_CONNECTED_SEC);
	}
#endif	

	nodelay(data->main_win, TRUE);
	clearok(data->main_win, FALSE); /* not completely redraw window*/
	curs_set(0);

	wclear(data->main_win);
	while (1)
	{
		ch = wgetch(data->main_win);
		/*odpal wyswietlanie na ekranie */
		switch (ch)
		{
		case KEY_DOWN:
			/* Go to next field */
			data->last_move = SNAKE_DOWN;
			break;
		case KEY_UP:
			/* Go to previous field */
			data->last_move = SNAKE_UP;
			break;
		case KEY_LEFT:
			/* Go to previous field */
			data->last_move = SNAKE_LEFT;
			break;
		case KEY_RIGHT:
			/* Go to previous field */
			data->last_move = SNAKE_RIGHT;
			break;
		case KEY_BACKSPACE:
			//data->last_move = KEY_BACKSPACE;
			//sp->backRevisionNum(10);
			break;
		default:
			/* If this is a normal character, it gets */
			/* Printed                                */
			//data->last_move = SNAKE;
			break;
		}

		
		 synchronizer->setClientLastDirection(0,data->last_move);
		 synchronizer->synchronize();
		 
		//move_result = sp->moveTo(data->last_move);
		

		gp_print_current_state(data);
		/* cleaning last changes - only changed fields will be redrawn*/
		MyMap::instanceOf()->cleanupLastChanges();
		usleep(TIME_DELAY * 1);
	}

}
